package com.bocek.chakmapoint.model;

import static org.junit.Assert.*;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;

import org.junit.*;

/**
 * Unit test for COval class.
 * 
 * @author  Baris Sencan
 * @version 1.1
 */
public class COvalTest {
	int thickness;
	Point p1, p2;
	COval oval;
	
	@Before
	public void setUp() {
		thickness = 2;
		p1 = new Point(10, 10);
		p2 = new Point(110, 110);
		oval = new COval(10, 10, 100, 100, Color.RED, thickness);
	}
	
	@Test
	public void test_getName() {
		assertEquals(oval.getName(), "Oval");
		
		assertTrue(oval.repOK());
	}
	
	@Test
	public void test_isPointInside() {
		// Blackbox tests
		assertTrue(oval.isPointInside(new Point(20, 40)));
		assertTrue(oval.repOK());
		assertFalse(oval.isPointInside(new Point(10, 9)));
		assertTrue(oval.repOK());
		
		// Glassbox test
		Ellipse2D.Double ellipse = new Ellipse2D.Double(10, 10, 100, 100);
		for (int x = 0; x <= 300; x++) {
			
			for (int y = 0; y <= 300; y++) {
				Point p = new Point(x, y);
				
				if (ellipse.contains(p)) {
					assertTrue(oval.isPointInside(p));
					assertTrue(oval.repOK());
				} else {
					assertFalse(oval.isPointInside(p));
					assertTrue(oval.repOK());
				}
			}
		}
	}
	
	@Test
	public void test_select() {
		// Blackbox tests
		assertTrue(oval.select(p1));
		oval.deselect();
		assertTrue(oval.repOK());
		
		assertTrue(oval.select(p2));
		oval.deselect();
		assertTrue(oval.repOK());
		
		assertTrue(oval.select(new Point(30, 50)));
		oval.deselect();
		assertTrue(oval.repOK());
		
		assertFalse(oval.select(new Point(110, 120)));
		oval.deselect();
		assertTrue(oval.repOK());
		
		// Glassbox tests
		for (int xdiff = -thickness; xdiff <= thickness; xdiff++) {
			
			for (int ydiff = -thickness; ydiff <= thickness; ydiff++) {
				assertTrue(oval.select(new Point((int) p1.getX() + xdiff, (int) p1.getY() + ydiff)));
				oval.deselect();
				
				assertTrue(oval.select(new Point((int) p2.getX() + xdiff, (int) p2.getY() + ydiff)));
				oval.deselect();
				
				assertTrue(oval.repOK());
			}
		}
		
		Ellipse2D.Double ellipse = new Ellipse2D.Double(10, 10, 100, 100);
		for (int x = 0; x <= 300; x++) {
			
			for (int y = 0; y <= 300; y++) {
				Point p = new Point(x, y);
				
				if (ellipse.contains(p) || p1.distance(p) <= thickness + 3 || p2.distance(p) <= thickness + 3) {
					assertTrue(oval.select(p));
					oval.deselect();
					assertTrue(oval.repOK());
				} else {
					assertFalse(oval.select(p));
					assertTrue(oval.repOK());
				}
			}
		}
	}
	
	@Test
	public void test_deselect() {
		oval.select(p1);
		
		assertTrue(oval.deselect());
		assertFalse(oval.deselect());
		
		assertTrue(oval.repOK());
	}
	
	@Test
	public void test_isSelected() {
		assertFalse(oval.isSelected());
		
		oval.select(p1);
		assertTrue(oval.isSelected());
		
		assertTrue(oval.repOK());
	}
	
	@Test
	public void test_move() {
		// Test moving the whole oval. (relocate)
		oval.select(new Point(40, 40));
		oval.move(new Point(5, 4));
		assertTrue(new Rectangle2D.Double(15, 14, 100, 100).equals(oval.getBounds2D()));
		oval.deselect();
		
		// Test moving the first corner point. (resize)
		oval.select(p1);
		oval.move(new Point(3, 7));
		assertTrue(new Rectangle2D.Double(13, 17, 97, 93).equals(oval.getBounds2D()));
		oval.deselect();
		
		// Test moving the second corner point. (resize)
		oval.select(p2);
		oval.move(new Point(10, 19));
		assertTrue(new Rectangle2D.Double(13, 17, 107, 112).equals(oval.getBounds2D()));
		oval.deselect();
		
		assertTrue(oval.repOK());
	}
	
	@Test
	public void test_isOutsideFrame() {
		Rectangle2D.Double frame;
		Dimension frameDimension;
		
		// Glassbox test
		for (int width = 0; width <= 500; width++) {
			
			for (int height = 0; height <= 500; height++) {
				frame = new Rectangle2D.Double(0, 0, width, height);
				frameDimension = new Dimension(width, height);
				
				if (frame.contains(oval.getBounds2D())) {
					assertFalse(oval.isOutsideFrame(frameDimension));
				} else {
					assertTrue(oval.isOutsideFrame(frameDimension));
				}
			}
		}
		
		assertTrue(oval.repOK());
	}
}
